#include "Socket.hpp"
#include "Epoller.hpp"
#include "nocopy.hpp"
#include <memory>

using std::string;
using std::cout;
using std::cin;
using std::endl;

const int maxnum = 64;
const int defaultfd = -1;
const int non_event = 0;
uint32_t EVENT_IN = (EPOLLIN);
uint32_t EVENT_OUT = (EPOLLOUT);


int debug_cnt = 0;

class EpollServer : public nocopy
{
public:
    EpollServer(uint16_t port)
    :_port(port)
    {
        _epoller_ptr = std::make_shared<Epoller>();
    }
    ~EpollServer()
    {
        _listensock.Close();
    }

    void InitServer()
    {
        _listensock.Socket();
        _listensock.Bind(_port);
        _listensock.Listen();
    }

    void Accepter()
    {
        int newsock = _listensock.Accpet(nullptr,nullptr);
        if(newsock < 0)
        {
            return;
        }

        log(Info,"Connect success");
        _epoller_ptr->EpollerUpdate(EPOLL_CTL_ADD, newsock, EVENT_IN);
    }

    void Receiver(int rfd)
    {
        char buffer[1024] = {0};
        ssize_t n = read(rfd, buffer, sizeof(buffer));      //注意读到的数据不一定完整噢
        if(n < 0)
        {
            log(Error, "read error");       //细节：移除时要保证文件描述符合法，故要先移除后关闭
            _epoller_ptr->EpollerUpdate(EPOLL_CTL_DEL,rfd, 0);
            close(rfd);
            
        }
        else if(n == 0)
        {   
            log(Info, "disconnect...");
            _epoller_ptr->EpollerUpdate(EPOLL_CTL_DEL,rfd, 0);
            close(rfd);
        }
        else
        {
            cout << "server says: " << buffer << endl;
        }
    }

    void Dispatcher(int n)
    {
        log(Info,"this is %d times to dispatch", debug_cnt++);
        for(int i = 0; i < n; i++)
        {
            if(_ep_events[i].events & EPOLLIN)
            {
                log(Debug, "fd is %d", _ep_events[i].data.fd);
                
                if(_ep_events[i].data.fd == _listensock.GetFd())
                {
                    Accepter();
                }
                else
                {
                    Receiver(_ep_events[i].data.fd);
                }
            }
        }
    }   

    void Start()
    {
        //先对listensock进行设置
        // _ep_events[0].data.fd = _listensock.GetFd();
        // _ep_events[0].events = POLLIN;
        _epoller_ptr->EpollerUpdate(EPOLL_CTL_ADD,_listensock.GetFd(),EVENT_IN);

        for(;;)
        {
           int n =  _epoller_ptr->EpollerWait(_ep_events, maxnum);

           if(n < 0)
           {
                log(Error, "EpollerWait failed.");
                break;
           }
           else if(n == 0)
           {
                log(Info, "Timeout.");
           }
           else
           {
                log(Debug, "retval of wait is %d", n);
                Dispatcher(n);
           }
           sleep(1);

        }
    }

private:
    epoll_event _ep_events[maxnum];      //所“捞取”的多个fd即对应事件集的“存放点”
    std::shared_ptr<Epoller> _epoller_ptr;
    Sock _listensock;
    uint16_t _port;
};